package com.mofum.scope.orm.mybatis.parse;

import com.mofum.scope.common.model.Permission;
import com.mofum.scope.common.model.Scope;
import com.mofum.scope.processor.impl.DefaultRestructureProcessor;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;

import java.util.*;

/**
 * @author yuyang@qxy37.com
 * @since 2019-04-25
 **/
public class SQLParseDemo {


    public static void main(String[] args) throws JSQLParserException {

        String sql = "select device.device_id,\n" +
                "       device.device_name,\n" +
                "       device.sort_id,\n" +
                "       device.days,\n" +
                "       sort.sort_name,\n" +
                "       case\n" +
                "         when TO_DAYS(max(log.create_time)) - TO_DAYS(device.last_time) <= device.days then 1\n" +
                "         else 0\n" +
                "         end as state\n" +
                "from ops_device as device\n" +
                "       join ops_project as project\n" +
                "            on device.project_id = project.project_id\n" +
                "       join ops_sort as sort\n" +
                "            on sort.id = device.sort_id\n" +
                "       left join ops_patrol_log as log\n" +
                "                 on log.device_id = device.device_id\n" +
                "where device.project_id = 'Pro_001'\n" +
                "group by device.device_id, device.last_time";

        Select originSelect = (Select) CCJSqlParserUtil.parse(sql);

        PlainSelect originPlainSelect = (PlainSelect) originSelect.getSelectBody();

        SQLParseDemo defaultRestructureProcessor = new SQLParseDemo();

        List<Scope> scopes = new ArrayList<>();

        Scope scope = new Scope();

        scope.setTableName("ops_device");

        scope.setColumn("create_time");

        scope.setId("admin");

        scopes.add(scope);

        Permission permission = new Permission();

        permission.setScopeCollections(scopes);

        defaultRestructureProcessor.wrapperPermission(originPlainSelect, permission);

        System.out.println(originPlainSelect.toString());


    }

    private void wrapperPermission(PlainSelect resultPlainSelect, Permission permission) {
        if (permission != null && permission.getScopeCollections() != null && permission.getScopeCollections().size() != 0) {
            List<Scope> scopes = permission.getScopeCollections();
            Map<String, List<Scope>> tableMap = new HashMap();

            Iterator var5;
            Scope scope;
            Object list;
            for(var5 = scopes.iterator(); var5.hasNext(); ((List)list).add(scope)) {
                scope = (Scope)var5.next();
                list = null;
                if (scope.getTableName() == null) {
                    list = (List)tableMap.get("");
                } else {
                    list = (List)tableMap.get(scope.getTableName());
                }

                if (list == null) {
                    list = new ArrayList();
                    tableMap.put(scope.getTableName(), (List<Scope>) list);
                }
            }

            var5 = tableMap.keySet().iterator();

            while(var5.hasNext()) {
                String table = (String)var5.next();
                this.wrapperScope(resultPlainSelect, table, (List)tableMap.get(table));
            }

        }
    }

    private void wrapperScope(PlainSelect resultPlainSelect, String table, List<Scope> scopes) {
        Map<String, List<String>> scopesMap = new HashMap();
        Iterator var5 = scopes.iterator();

        while(var5.hasNext()) {
            Scope scope = (Scope)var5.next();
            if (scope.getColumn() != null && !scope.getColumn().trim().equals("")) {
                List<String> data = (List)scopesMap.get(scope.getColumn());
                if (data == null) {
                    List<String> list = new ArrayList();
                    scopesMap.put(scope.getColumn(), list);
                }

                data = (List)scopesMap.get(scope.getColumn());
                data.add(scope.getId());
            }
        }

        var5 = scopesMap.keySet().iterator();

        while(var5.hasNext()) {
            String column = (String)var5.next();
            this.wrapperScopes(resultPlainSelect, table, column, (List)scopesMap.get(column));
        }

    }

    private void wrapperScopes(PlainSelect resultPlainSelect, String tableName, String columnName, List<String> scopes) {
        InExpression inExpression = new InExpression();
        Column column = new Column();
        column.setColumnName(columnName);
        column.setTable(new Table(tableName));
        inExpression.setLeftExpression(column);
        List<Expression> list = this.convertPermissionList(scopes);
        inExpression.setRightItemsList(new ExpressionList(list));
        Expression expression = resultPlainSelect.getWhere();
        if (expression == null) {
            resultPlainSelect.setWhere(inExpression);
        } else {
            Parenthesis parenthesis = new Parenthesis(expression);
            AndExpression andExpression = new AndExpression(parenthesis, inExpression);
            resultPlainSelect.setWhere(andExpression);
        }
    }

    private List<Expression> convertPermissionList(List<String> scopes) {
        List<Expression> expressions = new ArrayList();
        Iterator var3 = scopes.iterator();

        while(var3.hasNext()) {
            String scope = (String)var3.next();
            expressions.add(new StringValue(scope));
        }

        return expressions;
    }

}
